import type { RouteLocationNormalizedGeneric, RouteLocationNormalizedLoadedGeneric, RouteRecordRaw } from "vue-router";
import { ElMessage } from "element-plus";
import { isEqual } from "es-toolkit";
import { defineStore } from "pinia";
import { computed, nextTick, ref } from "vue";
import { multiTagsStorage } from "@/config/storage";
import { $t } from "@/plugins/i18n";
import router from "@/router";
import { useConfigStore } from "./config";
import { usePermissionStore } from "./permission";

interface BaseTag {
    path: string;
    query?: RouteLocationNormalizedGeneric["query"];
    params?: RouteLocationNormalizedGeneric["params"];
}

export interface MultiTag extends BaseTag {
    name: string; // route.name
    title?: string; // route.meta.title
    isFixed?: boolean; // route.meta.fixedTag
    isActive: boolean; // 是否为当前激活的标签
    isTitleUpdated: boolean; // 标题是否已经更新
}

/** 筛选路由信息 */
const routeToTag = (route: RouteRecordRaw | RouteLocationNormalizedGeneric): MultiTag => {
    return {
        path: route.path,
        name: route.name as string,
        query: (route as any).query || {},
        params: (route as any).params || {},
        title: route.meta?.title,
        isTitleUpdated: false,
        isFixed: route.meta?.fixedTag,
        isActive: false,
    };
};

/** 页签是否持久化 */
const multiTagsCache = computed(() => useConfigStore().config.MultiTagsCache);
/** 页面加载时必有的页签, 且不可删除 */
const fixedTag = usePermissionStore().flatteningRoutes.filter(v => v.meta?.fixedTag).map(route => routeToTag(route));

/** 页签功能 */
export const useMultiTagsStore = defineStore("multiTags", () => {
    /** 页签列表 */
    const multiTags = ref<MultiTag[]>(
        multiTagsCache.value
            ? (multiTagsStorage.value || fixedTag)
            : fixedTag,
    );

    /** 添加标签 */
    const addMultiTag = (route: RouteLocationNormalizedGeneric, callback?: () => void): void => {
        const tag = routeToTag(route);
        multiTags.value.push(tag);
        if (multiTagsCache.value) {
            multiTagsStorage.value = multiTags.value;
        }

        nextTick(() => {
            callback?.();
        });
    };

    /** 删除标签 */
    const removeMultiTag = (idx: number, callback?: () => void): void => {
        if (multiTags.value.length <= 1) {
            ElMessage({
                message: $t("description.warnLast"),
                type: "warning",
            });
            return;
        }

        const target = multiTags.value[idx];
        // 如果被删除的标签是激活状态, 则向前或向后一位跳转
        if (target.isActive) {
            if (idx > 0) {
                tagOnClick(multiTags.value[idx - 1]);
            } else {
                tagOnClick(multiTags.value[1]);
            }
        }

        multiTags.value.splice(idx, 1);

        if (multiTagsCache.value) {
            multiTagsStorage.value = multiTags.value;
        }

        nextTick(() => {
            callback?.();
        });
    };

    /** 改变标签激活 */
    const changeActiveTag = (idx: number, callback?: () => void): void => {
        multiTags.value.forEach((tag, i) => {
            tag.isActive = i === idx;
        });
        nextTick(() => {
            callback?.();
        });
    };

    /** 判断是否是同一个标签, 如果传参不同, 那么不是同一个标签 */
    const isSameTag = (originTag: BaseTag, targetTag: BaseTag): boolean => {
        return originTag.path === targetTag.path
            && isEqual(originTag.params || {}, targetTag.params || {})
            && isEqual(originTag.query || {}, targetTag.query || {});
    };

    /** 更新标题 */
    const updateTabTitle = (route: RouteLocationNormalizedLoadedGeneric, titleSuffix: string): void => {
        const tab = multiTags.value.find(t => isSameTag(t, route));
        if (tab && !tab.isTitleUpdated) {
            tab.title = `${tab.title} - ${titleSuffix}`;
            tab.isTitleUpdated = true;
        }
    };

    /** 标签点击事件 */
    const tagOnClick = (tag: MultiTag): void => {
        if (tag.name) {
            router.push({
                name: tag.name,
                query: tag.query,
                params: tag.params,
            });
        } else {
            router.push({ path: tag.path, query: tag.query });
        }
    };

    return {
        multiTags,
        addMultiTag,
        removeMultiTag,
        updateTabTitle,
        tagOnClick,
        isSameTag,
        changeActiveTag,
    };
});
